package com.example.baselibrary.utlis

import java.security.MessageDigest
import java.security.NoSuchAlgorithmException

/**
 * MD5加密工具类
 */
object Md5Util {

    private const val ALGORITHM_MD5 = "MD5"

    /**
     * 对字符串进行MD5加密
     *
     * @param input 需要加密的字符串
     * @return 加密后的32位小写十六进制字符串
     */
    fun encrypt(input: String): String {
        return try {
            val messageDigest = MessageDigest.getInstance(ALGORITHM_MD5)
            val bytes = messageDigest.digest(input.toByteArray())
            bytesToHex(bytes).lowercase()
        } catch (e: NoSuchAlgorithmException) {
            throw RuntimeException("MD5 algorithm not available", e)
        }
    }

    /**
     * 对字符串进行MD5加密并返回大写结果
     *
     * @param input 需要加密的字符串
     * @return 加密后的32位大写十六进制字符串
     */
    fun encryptUppercase(input: String): String {
        return encrypt(input).uppercase()
    }

    /**
     * 对字符串进行MD5加密（加盐）
     *
     * @param input 需要加密的字符串
     * @param salt 盐值
     * @return 加密后的32位小写十六进制字符串
     */
    fun encryptWithSalt(input: String, salt: String): String {
        return encrypt("$input$salt")
    }

    /**
     * 对字符串进行MD5加密（加盐）并返回大写结果
     *
     * @param input 需要加密的字符串
     * @param salt 盐值
     * @return 加密后的32位大写十六进制字符串
     */
    fun encryptWithSaltUppercase(input: String, salt: String): String {
        return encryptWithSalt(input, salt).uppercase()
    }

    /**
     * 将字节数组转换为十六进制字符串
     *
     * @param bytes 字节数组
     * @return 十六进制字符串
     */
    private fun bytesToHex(bytes: ByteArray): String {
        val hexChars = CharArray(bytes.size * 2)
        for (i in bytes.indices) {
            val v = bytes[i].toInt() and 0xFF
            hexChars[i * 2] = hexArray[v ushr 4]
            hexChars[i * 2 + 1] = hexArray[v and 0x0F]
        }
        return String(hexChars)
    }

    // 十六进制字符数组
    private val hexArray = "0123456789ABCDEF".toCharArray()

    /**
     * 验证输入字符串与已加密的MD5值是否匹配
     *
     * @param input 原始字符串
     * @param encrypted 已加密的MD5值
     * @return 是否匹配
     */
    fun verify(input: String, encrypted: String): Boolean {
        return encrypt(input) == encrypted.lowercase()
    }

    /**
     * 验证输入字符串与已加密的MD5值是否匹配（加盐验证）
     *
     * @param input 原始字符串
     * @param salt 盐值
     * @param encrypted 已加密的MD5值
     * @return 是否匹配
     */
    fun verifyWithSalt(input: String, salt: String, encrypted: String): Boolean {
        return encryptWithSalt(input, salt) == encrypted.lowercase()
    }
}
